/**

 */
package name.yzhu.database;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.tuple.Pair;
import org.hibernate.SQLQuery;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.ProjectionList;

/**
 * <p>
 * In generally , IDbUtil stands by a hibernate session, hence, closing it immediately after using it is a good practice.
 * Some synchronized problems may caused by this Object does not close. </br>
 * IDbutil does not commit anything automatically, It also do not synchorize object after any opertion. you should take care
 * these features</br>
 * Here list the major features of IDbUtil</br>
 * </p>
 * <h4>1 IDbUtil is a light object ,the creating cost equals to the cost of creating a hiberante session</h4>
 * <h4>2 IDbutil should be closed after using it, otherwise the hiberante session will be living until it was closed</h4>
 * <h4>3 IDbutil does not commit transaction in any condition, User should commit it when need</h4>
 * <h4>4 IDbutil mantians a hiberante session. before close it, the cache associated with session is alive</h4>
 *
 * <table border=2>
 * <tr><td><b>scene</b></td><td><b>How to use it</b></td></tr>
 * <tr><td>Read</td><td>Get a IDBUtil, read data，the close it</td></tr>
 * <tr><td>update a small set objects</td><td>Get a IDBUtil, read data，change data,save them,commitTrans ,close</td></tr>
 * <tr><td>select data, waiting for modifing.（most are waiting for user update),update object</td><td>
 * 			 close the IDbUtil after selecting. Then ,use a new IDbutil to update the user changing</td></tr>
 * <tr><td>transaction</td><td>make sure comitTrans after a series of opertions<br></tr>
 * <tr><td>long transaction</td><td>Do not think it exist, spliting the  long transaction.</td></tr>
 * </table>
 *
 *  <p>
 *  Althoght IDbutil is thread-saft , however ,using it acoress threads does not make sense. different threads will use different IDbutil which is
 *  guarnteed by {@link DbSupport}.
 *  </p>
 *
 *  <p>
 *  IDbutil will rollback automatically when a database exception occurs. user should handle the business exception.
 *  </p>
 *  <p>
 *  The following is an example:
 *  </p>
 * <pre>
 * try{
 *     db=// get IDbutil
 *     query objects.
 *     change objects
 *     updates these objects
 * }catch(DatabseException e){
 *     //Database exception may be thrown by optimism lock failed.
 *     //you can try this operation again ,or desert it .
 *     //<b>Rollbacking is not necessary</b>.
 * }catch(OtherException e){
 *     db.rollback(); // you should rollback manually, when catched business exception.
 * } finally{
 *     db.close();
 * }
 *
 *
 * </pre>
 *
 * @see DbSupport
 * @author yhzhu
 *
 */
public interface IDbUtil {
	public <T> List<T> queryListForHQL(String hql, int start,
			int pageUtil, String... params) throws DataBaseException;

	public long count(Class<?> clazz, List<Criterion> restrictions)
			throws DataBaseException;

	public long countDistinct(Class<?> clazz, List<Criterion> restrictions, String propertyName)
			throws DataBaseException;

	public Number sum(Class<?> clazz, List<Criterion> restrictions, String propertyName)
			throws DataBaseException;

	public Number avg(Class<?> clazz, List<Criterion> restrictions, String propertyName)
		throws DataBaseException;

	public ScrollableResults scroll(Class<?> clazz, List<Criterion> restrictions, int from,
			int count, String orderBy, boolean asc) throws DataBaseException;

	public  <T> List<T> criteriaRetrieve(Class<T> clazz, List<Criterion> restrictions,
			int from, int count, String orderByProperty, boolean asc)
			throws DataBaseException;

	public <T> T criteriaRetrieve(Class<T> clazz, List<Criterion> restrictions) throws DataBaseException;
	
 	public  <T> List<T> criteriaRetrieve(Class<T> clazz, List<Criterion> restrictions,
 			int from, int count, List<Pair<String, Boolean>> orderByAsc)
 			throws DataBaseException;

 	public  <T> List<T> criteriaRetrieveAll(Class<T> clazz, List<Criterion> restrictions,
 			List<Pair<String, Boolean>> orderByAsc)
 			throws DataBaseException;

	public long count(Class<?> clazz, List<Criterion> restrictions, Map<String, String> aliasMap)
			throws DataBaseException;

	public <T> List<T> criteriaRetrieve(Class<T> clazz, Map<String, String> aliasMap,
			List<Criterion> restrictions, int from, int count,
			List<Pair<String, Boolean>> orderByAsc) throws DataBaseException;

	public  <T> List<T>  projectionRetrieve(Class<T> clazz, List<Criterion> restrictions,
			ProjectionList pl, int from, int count, String orderByProperty, boolean asc)
			throws DataBaseException;

	public  void batchExecute(List<String> hqlList)
			throws DataBaseException;

	public  void saveOrUpdateOrDelForHQL(String hql,
			String... params) throws DataBaseException;

	public  <T> T getObjectForFun(String fun,
			String column, String object, String conds) throws DataBaseException;

	public <T> List<T> getAll(Class<T> classs) throws DataBaseException;

	public  <T> List<T> getObjectForList(Class<T> classs,
			int start, int pageUtil) throws DataBaseException;

	public   void update(Object obj)throws DataBaseException;

	public   void merge(Object obj) throws DataBaseException;


	public   Serializable save(Object obj) throws DataBaseException;

	public   void SaveOrUpdate(Object object) throws DataBaseException;

    public   void Delete(Object o) throws DataBaseException;

    public  <T> T getForObejct(Class<T> classs, Serializable id) throws DataBaseException;

    public void close();

    public void beginTrans()  throws DataBaseException;

    public  void commitTrans() throws DataBaseException;

    public  void flush() throws DataBaseException;

    void rollback();

    /**
     * execute hql sql for update or delete
     * @param sql
     * @param params
     * @return
     * @throws DataBaseException
     */
    public int executeHqlSql(String sql, Object... params) throws DataBaseException;
    /**
     * execute select native sql
     * @param sqlQuery
     * @return
     * @throws DataBaseException
     */
    public  List<?> selectNativeSQL(String sqlQuery, int start, int pageUtil, String... params) throws DataBaseException;
    /**
     * execute native sql: insert, update, delete
     * @param sql
     * @return
     * @throws DataBaseException
     */
    public int executeNativeSQL(String sql, String... params) throws DataBaseException;
    /**
	 * create native sql
	 * @param sql  the native SQL: select, insert, update, delete   
	 */
    public  SQLQuery createNativeSQL(String sql, String... params) throws DataBaseException;
    /**
     * create native sql with custom the sql parameter bind
     * @param sql
     * @param bind
     * @return
     * @throws DataBaseException
     */
	public int executeNativeSQL(String sql, SQLParameterBinder bind)
			throws DataBaseException;
	/**
	 * 
	 * @param sql
	 * @param param
	 * @return
	 * @throws DataBaseException
	 */
	public int executeNativeSQL(String sql, List<Object> param)
			throws DataBaseException;
	/**
	 * evict hibernate cache . <br> <b>note:</b> 
	 * @param entityClass
	 * @param id
	 */
	public void evict(Class<?> entityClass, Serializable id);
	/**
	 * 
	 * @return
	 */
	public Session getCurrentSession();
}
